/**
 * 数据存储结构分为存储器和索引器
 * 1. 存储器
 *   1) primaryData
 *      存储注入缩略图的json数组
 *   2) storeData
 *      收藏缩略图的json数组
 *   3) currentData
 *      当前json数组
 * 2. 索引器
 *   1) primaryIndexer
 *      记录数组的下表和缩略图ID之间的关系
 *   2) storeIndexer
 *      记录收藏数组的下表和收藏缩略图ID之间的关系
 *   3) currentIndexer
 *      当前索引器
 */
(function ($) {
  "use strict";

  var sprintf = function (str) {
    var args = arguments,
        flag = true,
        i = 1;

    str = str.replace(/%s/g, function () {
      var arg = args[i++];

      if (typeof arg === 'undefined') {
        flag = false;
        return '';
      }
      return arg;
    });
    return flag ? str : '';
  };
  var Map = function () {
    this.keys = new Array();
    this.values = new Array();
    this.data = new Array();
    this.index = new Array();
    //添加键值对
    this.set = function (key, value) {
      if (this.data[key] == null) {//如键不存在则身【键】数组添加键名
        if (this.keys.length >= 0) {
          this.index[value] = this.keys.length;
        }
        this.keys.push(key);
        this.values.push(value);
      }
      this.data[key] = value;//给键赋值
    };
    //获取键对应的值
    this.get = function (key) {
      return this.data[key];
    };
    //去除键值，(去除键数据中的键名及对应的值)
      this.remove = function (key) {
        this.keys.remove(key);
        delete this.index[this.data[key]];
        delete this.data[key];
      };
    //判断键值元素是否为空
    this.isEmpty = function () {
      return this.keys.length == 0;
    };
    //获取键值元素大小
    this.size = function () {
      return this.keys.length;
    };
    //遍历Map,执行处理函数. 回调函数 function(key,value,index){..}
    this.each = function(fn){
      if(typeof fn != 'function'){
        return;
      }
      var len = this.keys.length;
      for(var i=0;i<len;i++){
        var k = this.keys[i];
        fn(k,this.data[k],i);
      }
    };
    //获取键值数组,返回键值对象{key,value}的数组
    this.entrys = function() {
      var len = this.keys.length;
      var entrys = new Array(len);
      for (var i = 0; i < len; i++) {
        entrys[i] = {
          key : this.keys[i],
          value : this.data[this.keys[i]]
        };
      }
      return entrys;
    };
    //重写toString方法
    this.toString = function(){
      var s = "";
      for (var i = 0; i < this.keys.length; i++) {
        var k = this.keys[i];
        s += k+"="+this.data[k] + ',';
      }
      return "{" + s.substring(0, s.length - 1) + "}";
    };
  };
  var reSizeImage = function (image, dWidth, dHeight) {
    var img = $(image);
    var width = img.width();
    var height = img.height();
    if (width > dWidth) {
      var ratio = dWidth / width;
      img.css("width", dWidth);
      img.css("height", height * ratio);
      height = height * ratio;
      width = width * ratio;
    }
    if (height > dHeight) {
      ratio = dHeight / height;
      img.css("height", dHeight);
      img.css("width", width * ratio);
      width = width * ratio;
    }
  };

  var Thumbnail = function (el, options) {
    this.options = options;
    this.$el = $(el);
    this.timeout_ = 0;
    this.init();
  };

  Thumbnail.DEFAULTS = {
    options: {
      layout: 3, //每行几张
      mode: 'ordinary', //普通 灰阶 修补
      width: 500,  //缩略图宽度
      height: 600, //缩略图高度
      data: [],  //所有缩略图数据 有序Map 排序 eg. --> {key1=value1,key2=value2,key3=value3}
    }
  };

  Thumbnail.EVENTS = {
    'changeConditions': 'onChangeConditions'
  };

  Thumbnail.prototype.init = function () {
    this.initContainer();
    this.initToolBar();
    this.initData();
    this.initBody();
    this.initLocate();
  };
  Thumbnail.prototype.reload = function (data) {
    this.options.data = data;
    this.initData();
    this.initBody();
    this.initLocate();
  };
  Thumbnail.prototype.initLocate = function () {
    var id = this.currentIndexer.keys[0] + '_d';
    this.locate(id, this.options.onClickCell);
  }
  /**
   * 初始化框架(包括ToolBar&initBody)
   */
  Thumbnail.prototype.initContainer = function () {
    this.$container = $([
      '<div class="thumbnail" style="width:100%">',
      '<div class="row thumbnail-toolbar" style="width:100%"></div>',
      '<div class="row thumbnail-body"></div>',
      '</div>'
    ].join(''));
    this.$el.append(this.$container);
    this.thumbnailToolbar = this.$container.find('.thumbnail-toolbar');
    this.thumbnailBody = this.$container.find('.thumbnail-body');
    this.$el.css('width', this.options.width);
    this.$el.css('height', this.options.height);

  };

  /**
   * 初始化工具栏
   * 分页 & 布局
   */
  Thumbnail.prototype.initToolBar = function () {

    var html = [
      '<div class="btn-group col-xs-9" style="padding-right: 0px;padding-left: 0px;" role="group" aria-label="..." align="left">',
      '<button class="btn btn-warning page-pre">上一页</button>',
      '<button class="btn btn-success photo-pre">上一张</button>',
      '<button class="btn btn-success photo-next">下一张</button>',
      '<button class="btn btn-warning page-next">下一页</button>',
      '<button class="btn btn-warning view-store" title="查看收藏">★</button>',
      '<button class="btn btn-warning cancel-view-store" title="取消查看收藏">☆</button>',
      '</div><div class="col-xs-3" style="padding-right: 0px; padding-left: 0px;">',
      '<select class="form-control thumbnail-layout">',
      '<option value="2">每行两张</option>',
      '<option value="3" selected="selected">每行三张</option>',
      '<option value="4">每行四张</option>',
      '</select>',
      '</div>'
    ];

    this.thumbnailToolbar.append(html.join(''));
  };

  Thumbnail.prototype.initData = function (data) {
    var i, len, item, key, primaryIndexer, storeIndexer;
    this.primaryData = data || this.options.data;
    this.storeData = [];
    len = this.primaryData.length;
    primaryIndexer = new Map();
    storeIndexer = new Map();
    for (i = 0; i < len; i ++) {
      item = this.primaryData[i];
      key = item.panel_id + '_' + item.defect_no + '_' + item.jge_cnt + '_' + item.ope_id;
      primaryIndexer.set(key,i);
    }
    this.primaryIndexer = primaryIndexer;
    this.storeIndexer = storeIndexer;
  };

  /**
   * 根据事件(上/下一页&上/下一张&初始化&布局[每行几张])
   */
  Thumbnail.prototype.getData = function (index) {
    var first, layoutNum, page, dataStart, dataTo;

    first = this.thumbnailBody.find('.thumbnail-image')[0];
    if (this.options.mode === 'repair' || this.options.mode === 'gray'){
      layoutNum = 2;
    } else {
      layoutNum = this.options.layout * this.options.layout;
    }
    if (!first) {
      // TODO 如果this.currentData不存在赋值为[]是否合理
      return this.currentData ? this.currentData.slice(0, layoutNum) : [];
    }

    if (index) {
      if (index > this.currentData.length) {
        page = Math.ceil(this.currentData.length / layoutNum) || 1;
        dataStart = (page - 1) * layoutNum;
        dataTo = page * layoutNum;
      } else {
        page = Math.ceil((index + 1) / layoutNum) || 1;
        dataStart = (page - 1) * layoutNum;
        dataTo = page * layoutNum;
      }
    } else {
      dataStart = 0;
      dataTo = layoutNum;
    }
    // TODO 如果this.currentData不存在赋值为[]是否合理
    return this.currentData ? this.currentData.slice(dataStart, dataTo) : [];
  };

  Thumbnail.prototype.initThumbnail = function (id, path, alt) {
    var height, funBar, storeText, html = [];
    this.getThumbnailSize();
    height = this.options.funBar ? this.thumbnailHeight * 0.8 : this.thumbnailHeight;
    funBar = this.options.funBar ? '<div class="thumbnail-funBar"><button class="btn btn-default btn-xs '
        + 'thumbnail-store-btn" style="position:absolute; bottom:0px; ">收藏</button></div>' : '';
    if (this.storeIndexer.get(id.substring(0, id.length - 2)) >= 0) {
      storeText = '已收藏';
    } else {
      storeText = '收藏';
    }
    html.push('<div',
        sprintf(' style="position:relative; width:%spx;', this.thumbnailWidth),
        sprintf(' height:%spx"', this.thumbnailHeight),
        'class="thumbnail-cell" >',
        sprintf(' <div class="thumbnail-image" id="%s"', id),
        sprintf('style="margin:auto;text-align:center;height:%spx;">', height),
        sprintf(' <img src="%s"', path ? path : ''),
        ' class="img-responsive center-block"  alt="' + alt + '" /></div>'
        + '<div class="thumbnail-store-zone"> <a class="thumbnail-store" href="javascript:void(0);">'
        + '<i class="icon-heart-empty"></i> ' + storeText + ' </a> </div>',
        funBar,
        '</div>'
    );
    return html.join(' ');
  };

  /**
   * 通过获取到的数据拼接缩略图body
   */
  Thumbnail.prototype.initBody = function () {
    this.currentData = this.primaryData;
    this.currentIndexer = this.primaryIndexer;
    this.getCurrentBody();
  };
  Thumbnail.prototype.getCurrentBody = function (index) {
    var id,
        sid,
        alt,
        item,
        $prePage, $prePhoto, $nextPhoto, $nextPage, $layout, $viewStore, $canecelViewStore,
        that = this,
        data = that.getData(index),
        dataTo = data ? data.length : 0,
        thumbnailFragments = $(document.createDocumentFragment());

    for (var i = 0; i < dataTo; i++) {
      item = data[i];
      alt = '&#10;Panel ID:' + item.panel_id + '&#10;Defect No:' + item.defect_no + '&#10;Judge Cnt:' + item.jge_cnt + '&#10;Ope ID:' + item.ope_id;
      id = item.panel_id + '_' + item.defect_no + '_' + item.jge_cnt + '_' + item.ope_id + '_d';

      if (that.options.mode === 'ordinary') {
        thumbnailFragments.append(that.initThumbnail(id, item.ordinaryPath, alt));
      } else if (that.options.mode === 'gray') {
        that.options.layout = 2;
        sid = item.panel_id + '_' + item.defect_no + '_' + item.jge_cnt + '_' + item.ope_id + '_s';
        thumbnailFragments.append(that.initThumbnail(id, item.ordinaryPath, alt));
        thumbnailFragments.append(that.initThumbnail(sid, item.grayPath, alt));
      } else if (that.options.mode === 'repair') {
        that.options.layout = 2;
        sid = item.panel_id + '_' + item.defect_no + '_' + item.jge_cnt + '_' + item.ope_id + '_s';
        thumbnailFragments.append(that.initThumbnail(id, item.preRepair, alt));
        thumbnailFragments.append(that.initThumbnail(sid, item.postRepair, alt));
      } else {
        thumbnailFragments.append(that.initThumbnail(id, item.ordinaryPath, alt));
      }
    }
    //清空后再添加
    that.thumbnailBody.html(thumbnailFragments);
    $prePage = that.thumbnailToolbar.find('.page-pre');
    $prePhoto = that.thumbnailToolbar.find('.photo-pre');
    $nextPhoto = that.thumbnailToolbar.find('.photo-next');
    $nextPage = that.thumbnailToolbar.find('.page-next');
    $layout = that.thumbnailToolbar.find('.thumbnail-layout');
    $viewStore = that.thumbnailToolbar.find('.view-store');
    $canecelViewStore = that.thumbnailToolbar.find('.cancel-view-store');
    $prePage.off('click').on('click', $.proxy(this.onPagePre, this));
    $nextPage.off('click').on('click', $.proxy(this.onPageNext, this));

    $prePhoto.off('click').on('click', function () {
      var id, pre, key,
          images = that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image'),
          current = that.thumbnailBody.find('.thumbnail-success')[0];
      if(current) {
        key = current.id.substring(0, current.id.length - 2);
        pre = that.currentIndexer.data[key] - 1;
        if (pre < 0) {
          id = that.currentIndexer.keys[key] + '_d';
          that.options.onClickCell(that.thumbnailBody.find('#' + id));
          images.removeClass('thumbnail-success');
          $(current).addClass('thumbnail-success')
        } else {
          id = that.currentIndexer.keys[pre] + '_d';
          if (that.thumbnailBody.find('#' + id).length > 0) {
            that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image').removeClass('thumbnail-success');
            that.thumbnailBody.find('#' + id).addClass('thumbnail-success');
            that.options.onClickCell(that.thumbnailBody.find('#' + id));
          } else {
            that.locate(id, that.options.onClickCell);
          }
        }
      } else {
        //TODO
      }
    });
    $nextPhoto.off('click').on('click', function () {
      var id, next, length, key,
          images = that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image'),
          current = that.thumbnailBody.find('.thumbnail-success')[0];
      if(current) {
        key = current.id.substring(0, current.id.length - 2);
        next = that.currentIndexer.data[key] + 1;
        length = that.currentIndexer.keys.length;
        if (next > length - 1) {
          id = that.currentIndexer.keys[key] + '_d';
          that.options.onClickCell(that.thumbnailBody.find('#' + id));
          images.removeClass('thumbnail-success');
          $(current).addClass('thumbnail-success');
        } else {
          id = that.currentIndexer.keys[next] + '_d';
          if (that.thumbnailBody.find('#' + id).length > 0) {
            that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image').removeClass('thumbnail-success');
            that.thumbnailBody.find('#' + id).addClass('thumbnail-success');
            that.options.onClickCell(that.thumbnailBody.find('#' + id));
          } else {
            that.locate(id, that.options.onClickCell);
          }
        }
      }
    });

    $layout.off('change').on('change', function () {
      var id;
      that.options.layout = $(this).val();
      that.initBody();
      if (that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image').length > 0) {
        id = that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image')[0].id;
      }
      that.locate(id, that.options.onClickCell);
    });
    $viewStore.off('click').on('click', function () {
      that.currentData = that.storeData;
      that.currentIndexer = that.storeIndexer;
      that.getCurrentBody();
    });
    $canecelViewStore.off('click').on('click', function () {
      that.currentData = that.primaryData;
      that.currentIndexer = that.primaryIndexer;
      that.getCurrentBody();
    });
    var width = that.thumbnailWidth - 10;
    var height = that.options.funBar ? this.thumbnailHeight * 0.8 : this.thumbnailHeight;
    that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image').find('img').off('load').on('load', function () {
      reSizeImage(this, width, height);
    });
    that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image').off('click').on('click', function () {
      var tid, currentImg, $thumbnail = $(this);
      currentImg = that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image.thumbnail-success');
      typeof ( that.options.onClickCell) === 'function' && that.options.onClickCell($thumbnail, currentImg);
      tid = that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image.thumbnail-success');
      if (tid) {
        if (tid[0] != undefined && tid[0].id === $thumbnail[0].id) {

        } else {
          that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image').removeClass('thumbnail-success');
          $thumbnail.addClass('thumbnail-success');
        }
      } else {
        that.thumbnailBody.find('.thumbnail-cell > .thumbnail-image').removeClass('thumbnail-success');
        $thumbnail.addClass('thumbnail-success');
      }

    });
    that.thumbnailBody.find('.thumbnail-cell > .thumbnail-store-zone > .thumbnail-store').off('click').on('click', function (){
      var length, id = $(this).parent().prev()[0].id, key = id.substring(0, id.length - 2), index = that.primaryIndexer.data[key];
      item = that.primaryData[index];
      key = item.panel_id + '_' + item.defect_no + '_' + item.jge_cnt + '_' + item.ope_id;
      // 如果包含在storeIndexer内，则取消收藏
      if ($.inArray(key, that.storeIndexer.keys) < 0) {
        length = that.storeData.push(item);
        that.storeIndexer.set(key,length - 1);
        $(this).text('已收藏');
      } else {
        var indexerTmp = new Map(), dataTmp = [], len = that.storeData.length;
        for (var i = 0; i < len; i++) {
          var t = that.storeData[i];
          var k = t.panel_id + '_' + t.defect_no + '_' + t.jge_cnt + '_' + t.ope_id;
          if (key != k) {
            var l = dataTmp.push(t);
            indexerTmp.set(k, l);
          }
        }
        that.storeIndexer = indexerTmp;
        that.storeData = dataTmp;
        $(this).text('收藏');
      }

    });
    if (that.options.mode === 'repair' || that.options.mode === 'gray') {
      $('.thumbnail-layout').val(2);
    }
  };
  /**
   * 定位缩略图
   */
  Thumbnail.prototype.locate = function (id, callback) {
    var key, index, $id;
    if (id) {
      key = id.substring(0, id.length - 2);
      index = this.currentIndexer.data[key];
      this.getCurrentBody(index);
      $id = this.thumbnailBody.find('#' + id);
    } else {
      this.initBody();
      if (this.thumbnailBody.find('.thumbnail-cell > .thumbnail-image').length > 0) {
        id = this.thumbnailBody.find('.thumbnail-cell > .thumbnail-image')[0].id;
        $id = $(this.thumbnailBody.find('.thumbnail-cell > .thumbnail-image')[0]);
      }
    }
    this.thumbnailBody.find('.thumbnail-cell > .thumbnail-image').removeClass('thumbnail-success');
    if ($id) {
      $id.addClass('thumbnail-success');
    }
    typeof (callback) === 'function' && callback(this.thumbnailBody.find('#' + id));
  };

  Thumbnail.prototype.destroy = function () {
    this.primaryData = [];
    this.storeData = [];
    this.currentData = [];
    this.primaryIndexer = {};
    this.storeIndexer = {};
    this.currentIndexer = {};
    this.options = {};
    this.$container.next().remove();
    this.$container.remove();
    this.$el.html();
  };

  /**
   * 通过layout获取缩略图的大小
   * @param layout
   */
  Thumbnail.prototype.getThumbnailSize = function () {
    var layout, width, height;

    layout = this.options.layout;
    width = this.options.width;
    height = this.options.height;

    this.thumbnailWidth = Math.floor(width / layout);
    this.thumbnailHeight = Math.floor(height / layout);
  };

  Thumbnail.prototype.onPagePre = function () {
    var id, nextNum, key,
        first = this.thumbnailBody.find('.thumbnail-image')[0];

    if (first) {
      key = first.id.substring(0, first.id.length - 2);
      if (this.options.mode === 'ordinary') {
        nextNum = this.currentIndexer.data[key] - this.options.layout *  this.options.layout;
      } else {
        nextNum = this.currentIndexer.data[key] - 2;
      }
      if (nextNum >= 0) {
        id = this.currentIndexer.keys[nextNum] + '_d';
        this.locate(id, this.options.onClickCell);
      }
    }
  };

  Thumbnail.prototype.onPageNext = function () {
    var id, nextNum, key,
        first = this.thumbnailBody.find('.thumbnail-image')[0];

    if (first) {
      key = first.id.substring(0, first.id.length - 2);
      if (this.options.mode === 'ordinary') {
        nextNum = this.currentIndexer.data[key] + this.options.layout *  this.options.layout;
      } else {
        nextNum = this.currentIndexer.data[key] + 2;
      }

      if (nextNum < this.currentIndexer.keys.length) {
        id = this.currentIndexer.keys[nextNum] + '_d';
        this.locate(id, this.options.onClickCell);
      }
    }
  };

  /**
   * 清空缩略图
   */
  Thumbnail.prototype.clear = function () {
    //TODO
  };

  var allowedMethods = ['locate', 'reload', 'destroy'];
  $.fn.thumbnail = function (option) {
    var value,
        args = Array.prototype.slice.call(arguments, 1);

    this.each(function () {
      var $this = $(this),
          data = $this.data('thumbnail.data'),
          options = $.extend({}, Thumbnail.DEFAULTS.options, $this.data(),
              typeof option === 'object' && option);
      if (typeof option === 'string') {
        if ($.inArray(option, allowedMethods) < 0) {
          throw new Error("Unknown method: " + option);
        }

        if (!data) {
          return;
        }

        value = data[option].apply(data, args);

        if (option === 'destroy') {
          $this.removeData('thumbnail.data');
        }
      }

      if (!data) {
        $this.data('thumbnail.data', (data = new Thumbnail(this, options)));
      }
    });

    return typeof value === 'undefined' ? this : value;
  };
  $.fn.thumbnail.defaults = Thumbnail.DEFAULTS;

  $(function () {
  });
})(jQuery);
